package com.id.supaclean.ui.junk

import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.AnimationUtils
import android.view.animation.LinearInterpolator
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.id.supaclean.MyApplication.Companion.appContext
import com.id.supaclean.R
import com.id.supaclean.utils.*

/**
 * Created by YiGo on 2022/6/16.
 */
class CleanAdapter(private val fragment: Fragment) :
    RecyclerView.Adapter<RecyclerView.ViewHolder>() {


    private var data = mutableListOf<WrapperGarbage>()




    val viewModel by lazy { ViewModelProvider(fragment.requireActivity()).get(JunkViewModel::class.java) }


    fun View.onDelayClick(delay: Long = 500L, onClick: (View) -> Unit) {
        var last = 0L
        setOnClickListener {
            val now = System.currentTimeMillis()
            if (now - last <= delay) return@setOnClickListener
            last = now
            onClick(it)
        }
    }

    fun initAdapterData(newData: MutableList<WrapperGarbage>) {
        data.clear()
        newData.add(0, WrapperGarbage.Header)
        data.addAll(newData)
        notifyDataSetChanged()
    }

    private fun updateView(oldData: List<WrapperGarbage>, newData: List<WrapperGarbage>) {

        val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
            override fun getOldListSize(): Int = oldData.size
            override fun getNewListSize(): Int = newData.size
            override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
                val oldInfo = oldData[oldItemPosition]
                val newInfo = newData[newItemPosition]

                if (oldInfo is WrapperGarbage.Group && newInfo is WrapperGarbage.Group) {
                    return oldInfo.isShowed == newInfo.isShowed && oldInfo.isChecked == newInfo.isChecked
                }

                if (oldInfo is WrapperGarbage.Item && newInfo is WrapperGarbage.Item) {
                    return oldInfo.garbage == newInfo.garbage && oldInfo.isChecked == newInfo.isChecked
                }

                if (oldInfo is WrapperGarbage.Header) return true

                return false
            }

            override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
                return oldData[oldItemPosition] == newData[newItemPosition]
            }

        })

        diffResult.dispatchUpdatesTo(this)

    }

    fun showItem(group: WrapperGarbage.Group) {
        if (group.isShowed) return
        val index = data.indexOf(group)
        if (index == -1 || group.items.isEmpty()) return

        val oldData = data
        group.isShowed = true
        data = data.toMutableList().apply {
            addAll(index + 1, group.items)
        }
        updateView(oldData, data)

    }

    fun hideItem(group: WrapperGarbage.Group) {
        if (!group.isShowed) return
        val index = data.indexOf(group)
        if (index == -1 || group.items.isEmpty()) return

        val oldData = this.data
        group.isShowed = false
        this.data = this.data.toMutableList().apply {
            group.items.forEach { remove(it) }
        }
        updateView(oldData, this.data)
    }


    companion object {
        const val HEAD_TYPE = 0
        const val BIG_TYPE = 1
        const val DETAIL_TYPE = 2
    }


    inner class HeadViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val totalJunkTextView = view.findViewById<TextView>(R.id.totol_junk_tv)
        val unitTextView = view.findViewById<TextView>(R.id.unit_tv)
    }

    inner class BigViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val bigCheckBox =
            view.findViewById<com.id.supaclean.widget.checkbox.IndeterminateCheckBox>(R.id.big_checkBox)
        val bigName = view.findViewById<TextView>(R.id.big_name_tv)
        val expandImageView = view.findViewById<ImageView>(R.id.expand_iv)
    }

    inner class DetailViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val detailIcon = view.findViewById<ImageView>(R.id.detail_icon_iv)
        val detailName = view.findViewById<TextView>(R.id.detail_name_tv)
        val detailSize = view.findViewById<TextView>(R.id.detail_size_tv)
        val detailCheckBox = view.findViewById<CheckBox>(R.id.detail_checkBox)
    }


    override fun getItemViewType(position: Int): Int {
        if (position == 0) {
            return HEAD_TYPE
        } else if (data[position] is WrapperGarbage.Group) {
            return BIG_TYPE
        }
        return DETAIL_TYPE
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        if (viewType == HEAD_TYPE) {
            val headView =
                LayoutInflater.from(parent.context).inflate(R.layout.item_header, parent, false)
            return HeadViewHolder(headView)
        } else if (viewType == BIG_TYPE) {
            val bigView =
                LayoutInflater.from(parent.context).inflate(R.layout.item_big, parent, false)
            val bigViewHolder = BigViewHolder(bigView)
            return bigViewHolder
        } else {
            val detailView =
                LayoutInflater.from(parent.context).inflate(R.layout.item_detail, parent, false)
            val detailViewHolder = DetailViewHolder(detailView)
            return detailViewHolder
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val index = position
        val wrapperGarbage = data[index]
        if (holder is HeadViewHolder) {
            val garbageNumObserver = Observer<String> {
                holder.totalJunkTextView.text = it
            }
            val garbageUnitObserver = Observer<String> {
                holder.unitTextView.text = it
            }
            viewModel.currentPreGarbageNum.observe(this.fragment, garbageNumObserver)
            viewModel.currentPreGarbageUnit.observe(this.fragment, garbageUnitObserver)
        } else if (holder is BigViewHolder && wrapperGarbage is WrapperGarbage.Group) {
//            wrapperGarbage as WrapperGarbage.Group
            holder.bigName.text = wrapperGarbage.title
            if (wrapperGarbage.isChecked == false) {
                holder.bigCheckBox.isChecked = false
            } else if (wrapperGarbage.isChecked == null) {
                holder.bigCheckBox.isIndeterminate = true
            } else {
                holder.bigCheckBox.isChecked = true
            }
            holder.expandImageView.onDelayClick {
                if (!wrapperGarbage.isShowed) it.animate().rotation(180f) else it.animate()
                    .rotation(0f)
                if (wrapperGarbage.isShowed) {
                    hideItem(wrapperGarbage)
                } else {
                    showItem(wrapperGarbage)
                }
            }
            holder.bigCheckBox.setOnClickListener {


                val isCheck = when (wrapperGarbage.isChecked) {
                    true -> false
                    false -> true
                    else -> false
                }
                holder.bigCheckBox.isIndeterminate = false
                holder.bigCheckBox.isChecked = isCheck
                wrapperGarbage.isChecked = isCheck

                if (wrapperGarbage.isChecked != null && wrapperGarbage.isChecked == true) {
                    wrapperGarbage.items.forEach {
                        it.isChecked = true
                        viewModel.preCleanGarbage.add(it.garbage)
                    }
                    val size = viewModel.countGarbage(viewModel.preCleanGarbage.toList())
                    val unit =
                        smartChangeUint(size)
                    viewModel.currentPreGarbageUnit.value = unit
                    viewModel.currentPreGarbageNum.value = caculate(unit, size)
                } else {
                    wrapperGarbage.items.forEach {
                        it.isChecked = false
                        viewModel.preCleanGarbage.remove(it.garbage)
                    }
                    val size = viewModel.countGarbage(viewModel.preCleanGarbage.toList())
                    val unit =
                        smartChangeUint(size)
                    viewModel.currentPreGarbageUnit.value = unit
                    viewModel.currentPreGarbageNum.value = caculate(unit, size)
                }
                notifyDataSetChanged()
            }
        } else if (holder is DetailViewHolder && wrapperGarbage is WrapperGarbage.Item) {
            holder.detailCheckBox.isChecked = wrapperGarbage.isChecked
            if (wrapperGarbage.garbage is Garbage.Apk) {
                holder.detailName.text = "Apk"
                holder.detailName.text = wrapperGarbage.garbage.filename
                if (wrapperGarbage.garbage.icon != null) {
                    try {
                        holder.detailIcon.setImageDrawable(wrapperGarbage.garbage.getIcon())
                    } catch (e: Exception) {
                        holder.detailIcon.setImageResource(R.drawable.ic_launcher_foreground)
                    }
                }
                holder.detailCheckBox.isChecked = wrapperGarbage.isChecked
                holder.detailCheckBox.setOnClickListener {
                    wrapperGarbage.isChecked = !wrapperGarbage.isChecked
                    if (wrapperGarbage.isChecked) {
                        viewModel.preCleanGarbage.add(wrapperGarbage.garbage)
                        val size = viewModel.countGarbage(viewModel.preCleanGarbage.toList())
                        val unit =
                            smartChangeUint(size)
                        viewModel.currentPreGarbageUnit.value = unit
                        viewModel.currentPreGarbageNum.value = caculate(unit, size)
                    } else {
                        viewModel.preCleanGarbage.remove(wrapperGarbage.garbage)
                        val size = viewModel.countGarbage(viewModel.preCleanGarbage.toList())
                        val unit =
                            smartChangeUint(size)
                        viewModel.currentPreGarbageUnit.value = unit
                        viewModel.currentPreGarbageNum.value = caculate(unit, size)
                    }
                    //往上遍历找到父集
                    var pressPosition = index
                    while (data[pressPosition] is WrapperGarbage.Item && pressPosition >= 0) {
                        pressPosition--
                    }
                    //做判断
                    val group = data[pressPosition]

                    var isAllChosen = true
                    var isNoneChosen = true
                    if (group is WrapperGarbage.Group) {
                        group.items.forEach {
                            if (it.isChecked) {
                                isNoneChosen = false
                                return@forEach
                            }
                        }
                        group.items.forEach {
                            if (!it.isChecked) {
                                isAllChosen = false
                                return@forEach
                            }
                        }
                    }
                    if (isAllChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = true
                        }
                    }
                    if (isNoneChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = false
                        }
                    }
                    if (!isNoneChosen && !isAllChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = null
                        }
                    }
                    Log.w("cdm", "CleanAdapter.onBindViewHolder -> ${viewModel.preCleanGarbage}")
                    notifyDataSetChanged()
                }
                val size = wrapperGarbage.garbage.file.length()
                val unit = smartChangeUint(size)
                holder.detailSize.text = "${caculate(unit, size)} $unit"
                //size
            }
            if (wrapperGarbage.garbage is Garbage.EmptyFile) {
                holder.detailName.text = "Empty File"
                holder.detailName.text = wrapperGarbage.garbage.filename
                holder.detailIcon.setImageDrawable(appContext.getDrawable(R.mipmap.ic_empty_file))
                holder.detailCheckBox.isChecked = wrapperGarbage.isChecked
                holder.detailCheckBox.setOnClickListener {
                    wrapperGarbage.isChecked = !wrapperGarbage.isChecked
                    if (wrapperGarbage.isChecked) {
                        viewModel.preCleanGarbage.add(wrapperGarbage.garbage)
                        val size = viewModel.countGarbage(viewModel.preCleanGarbage.toList())
                        val unit =
                            smartChangeUint(size)
                        viewModel.currentPreGarbageUnit.value = unit
                        viewModel.currentPreGarbageNum.value = caculate(unit, size)
                    } else {
                        viewModel.preCleanGarbage.remove(wrapperGarbage.garbage)
                        val size = viewModel.countGarbage(viewModel.preCleanGarbage.toList())
                        val unit =
                            smartChangeUint(size)
                        viewModel.currentPreGarbageUnit.value = unit
                        viewModel.currentPreGarbageNum.value = caculate(unit, size)
                    }
                    //往上遍历找到父集
                    var pressPosition = index
                    while (data[pressPosition] is WrapperGarbage.Item && pressPosition >= 0) {
                        pressPosition--
                    }
                    //做判断
                    val group = data[pressPosition]

                    var isAllChosen = true
                    var isNoneChosen = true
                    if (group is WrapperGarbage.Group) {
                        group.items.forEach {
                            if (it.isChecked) {
                                isNoneChosen = false
                                return@forEach
                            }
                        }
                        group.items.forEach {
                            if (!it.isChecked) {
                                isAllChosen = false
                                return@forEach
                            }
                        }
                    }
                    if (isAllChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = true
                        }
                    }
                    if (isNoneChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = false
                        }
                    }
                    if (!isNoneChosen && !isAllChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = null
                        }
                    }
                    Log.w("cdm", "CleanAdapter.onBindViewHolder -> ${viewModel.preCleanGarbage}")
                    notifyDataSetChanged()
                }
                val size = wrapperGarbage.garbage.file.length()
                val unit = smartChangeUint(size)
                holder.detailSize.text = "${caculate(unit, size)} $unit"
                //size
            }
            if (wrapperGarbage.garbage is Garbage.Thumbnail) {
                holder.detailName.text = "Thumbnail"
                holder.detailName.text = wrapperGarbage.garbage.filename
                holder.detailIcon.setImageDrawable(appContext.getDrawable(R.mipmap.ic_thumnail))
                holder.detailCheckBox.isChecked = wrapperGarbage.isChecked
                holder.detailCheckBox.setOnClickListener {
                    wrapperGarbage.isChecked = !wrapperGarbage.isChecked
                    if (wrapperGarbage.isChecked) {
                        viewModel.preCleanGarbage.add(wrapperGarbage.garbage)
                        val size = viewModel.countGarbage(viewModel.preCleanGarbage.toList())
                        val unit =
                            smartChangeUint(size)
                        viewModel.currentPreGarbageUnit.value = unit
                        viewModel.currentPreGarbageNum.value = caculate(unit, size)
                    } else {
                        viewModel.preCleanGarbage.remove(wrapperGarbage.garbage)
                        val size = viewModel.countGarbage(viewModel.preCleanGarbage.toList())
                        val unit =
                            smartChangeUint(size)
                        viewModel.currentPreGarbageUnit.value = unit
                        viewModel.currentPreGarbageNum.value = caculate(unit, size)
                    }
                    //往上遍历找到父集
                    var pressPosition = index
                    while (data[pressPosition] is WrapperGarbage.Item && pressPosition >= 0) {
                        pressPosition--
                    }
                    //做判断
                    val group = data[pressPosition]

                    var isAllChosen = true
                    var isNoneChosen = true
                    if (group is WrapperGarbage.Group) {
                        group.items.forEach {
                            if (it.isChecked) {
                                isNoneChosen = false
                                return@forEach
                            }
                        }
                        group.items.forEach {
                            if (!it.isChecked) {
                                isAllChosen = false
                                return@forEach
                            }
                        }
                    }
                    if (isAllChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = true
                        }
                    }
                    if (isNoneChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = false
                        }
                    }
                    if (!isNoneChosen && !isAllChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = null
                        }
                    }
                    Log.w("cdm", "CleanAdapter.onBindViewHolder -> ${viewModel.preCleanGarbage}")
                    notifyDataSetChanged()
                }
                val size = wrapperGarbage.garbage.file.length()
                val unit = smartChangeUint(size)
                holder.detailSize.text = "${caculate(unit, size)} $unit"
                //size
            }
            if (wrapperGarbage.garbage is Garbage.Cache) {
                holder.detailName.text = "Cache"
                holder.detailName.text = wrapperGarbage.garbage.filename
                holder.detailIcon.setImageDrawable(appContext.getDrawable(R.drawable.ic_baseline_cached_24))
                holder.detailCheckBox.isChecked = wrapperGarbage.isChecked
                holder.detailCheckBox.setOnClickListener {
                    wrapperGarbage.isChecked = !wrapperGarbage.isChecked
                    if (wrapperGarbage.isChecked) {
                        viewModel.preCleanGarbage.add(wrapperGarbage.garbage)
                        val size = viewModel.countGarbage(viewModel.preCleanGarbage.toList())
                        val unit =
                            smartChangeUint(size)
                        viewModel.currentPreGarbageUnit.value = unit
                        viewModel.currentPreGarbageNum.value = caculate(unit, size)
                    } else {
                        viewModel.preCleanGarbage.remove(wrapperGarbage.garbage)
                        val size = viewModel.countGarbage(viewModel.preCleanGarbage.toList())
                        val unit =
                            smartChangeUint(size)
                        viewModel.currentPreGarbageUnit.value = unit
                        viewModel.currentPreGarbageNum.value = caculate(unit, size)
                    }
                    //往上遍历找到父集
                    var pressPosition = index
                    while (data[pressPosition] is WrapperGarbage.Item && pressPosition >= 0) {
                        pressPosition--
                    }
                    //做判断
                    val group = data[pressPosition]

                    var isAllChosen = true
                    var isNoneChosen = true
                    if (group is WrapperGarbage.Group) {
                        group.items.forEach {
                            if (it.isChecked) {
                                isNoneChosen = false
                                return@forEach
                            }
                        }
                        group.items.forEach {
                            if (!it.isChecked) {
                                isAllChosen = false
                                return@forEach
                            }
                        }
                    }
                    if (isAllChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = true
                        }
                    }
                    if (isNoneChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = false
                        }
                    }
                    if (!isNoneChosen && !isAllChosen) {
                        if (group is WrapperGarbage.Group) {
                            group.isChecked = null
                        }
                    }
                    Log.w("cdm", "CleanAdapter.onBindViewHolder -> ${viewModel.preCleanGarbage}")
                    notifyDataSetChanged()
                }
                val size = wrapperGarbage.garbage.file.length()
                val unit = smartChangeUint(size)
                holder.detailSize.text = "${caculate(unit, size)} $unit"
                //size
            }
        }
    }

    override fun getItemCount(): Int = data.size
}